package net.takela.push.service.sp.impl;


import jakarta.annotation.PostConstruct;
import net.takela.common.spring.exception.ParamException;
import net.takela.common.spring.http.HttpRequest;
import net.takela.common.spring.http.HttpRequestBuilder;
import net.takela.common.spring.http.HttpResponse;
import net.takela.common.spring.http.StatusCode;
import net.takela.common.utils.HashMapBuilder;
import net.takela.common.utils.StringUtils;
import net.takela.push.dao.PushAppDao;
import net.takela.push.model.PushApp;
import net.takela.push.model.PushMsgTpl;
import net.takela.push.model.PushWeChatTplMsg;
import net.takela.push.service.sp.ServiceProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by baboy on 25/07/2017.
 */
@Service("wechatPushService")
public class WeChatSerivceProvider extends ServiceProvider {
    private static final Logger logger = LoggerFactory.getLogger(WeChatSerivceProvider.class);
    @Autowired
    private ThreadPoolTaskExecutor executor;

    @Autowired
    private PushAppDao pushAppDao;
    @Value("${wechat.api.sendTplMsg}")
    private String sendTplMsgApi;

    private static Map<String, String> accessTokenPool = new HashMap();

    @PostConstruct
    public void init(){
        updateAllWechatAccessToken();
    }
    /**
     * second as well as minute, hour, day of month, month, day of week
     */
    @Scheduled(cron = "0 */1 * * * ?")
    public void updateAllWechatAccessToken(){
        List<PushApp> pushApps = pushAppDao.getAppsByType(PushApp.APP_SP_WECHAT);
        if(pushApps.size()>0){
            for (int i = 0; i< pushApps.size(); i++){
                PushApp pushApp = pushApps.get(i);
                Map conf = pushApp.getConf();
                String appId = (String)conf.get("appId");
                String getAccessTokenApi = (String) conf.get("getAccessTokenApi");
                asyncUpdateAccessToken(appId, getAccessTokenApi);
            }
        }
    }

    public void asyncUpdateAccessToken(final  String appId, final String getAccessTokenApi){
        executor.execute(new Runnable() {
            @Override
            public void run() {
                updateAccessToken(appId, getAccessTokenApi);
            }
        });
    }

    /**
     * 从我们别的服务器同步accesstoken
     * @param appId
     * @param getAccessTokenApi
     */
    public void updateAccessToken(String appId,  String getAccessTokenApi) {
    }

    /**
     * 根据appId获取AccessToken
     * @param appId
     * @return
     */
    public String getAccessToken(String appId) {
        return accessTokenPool.get(appId);
    }

    private HttpResponse sendMsg(String appId, PushWeChatTplMsg msg){

        String c = msg.getMsgBody();
        Map<String, String> headers = (Map<String, String>)HashMapBuilder.custom(String.class, String.class).build().put("conetnt-type","application/json");
        HttpRequest request = HttpRequestBuilder.builder().setHttpMethod(HttpMethod.POST).setRequestHeaders(headers).setRequestBody(c).build();
        String accessToken = getAccessToken(appId);
        String api = sendTplMsgApi+"?access_token="+accessToken;
        HttpResponse response = null;
        try {
            Map data = (Map)request.request();
            logger.info("SEND_WECHAT_MSG|token:" + accessToken +"|to:"+msg.getToOpenId()+"|"+msg.getTemplateId()+ "|" + response.toString());
            if (data != null ){
                Object errCode = data.get("errcode");
                if(errCode != null ){
                    if ("0".equals( errCode.toString())){
                        return response;
                    }
                }
                if (data.containsKey("errmsg")){
                    response.setMessage(data.get("errmsg").toString());
                }
            }
            response.setCode(StatusCode.ERROR.getCode());
            return response;
        } catch (Exception e) {
            e.printStackTrace();
            response = HttpResponse.error();
            response.setMessage(e.getMessage());
            return response;
        }
    }
    @Override
    public HttpResponse send(String msgCode, Map data, String ip) {
        PushMsgTpl msgTpl = getMsgTpl(msgCode);
        Map conf = msgTpl.getConf();
        String appId = (String)getPushApp().getConf().get("appId");

        Map dataMap = new HashMap();
        if(conf.containsKey("data")){
            dataMap.putAll( (Map)conf.get("data") );
        }
        dataMap.putAll(data);

        PushWeChatTplMsg msg = new PushWeChatTplMsg();
        if (data.containsKey("url")){
            Object ov = data.get("url");
            String v = ov == null ? null : ov.toString();
            msg.setUrl(v);
        }
        if (conf.containsKey("keys")){
            Map<String,String> keys = (Map) conf.get("keys");
            for (Map.Entry<String, String> keyMap :keys.entrySet()){
                String k = keyMap.getKey();
                String k2 = keyMap.getValue();
                Object ov = dataMap.get(k2);
                String v = ov==null ? null:ov.toString();
                if(k.equals("first")){
                    v += "\n";
                }
                if(k.equals("remark")){
                    v = "\n"+v;
                }
                if(v != null){
                    v = StringUtils.formatPlaceholders(v,dataMap);
                }
                msg.addData(k, v,null);
            }
        }
        String openIds = (String)dataMap.get("openId");
        if (org.apache.commons.lang3.StringUtils.isEmpty(openIds)){
            throw new ParamException("param.error.desc","openId");
        }
        String a[] = openIds.split(",");
        HttpResponse response = null;
        for (int i = 0; i <a.length; i++){
            String openId = a[i];
            msg.setTemplateId(msgTpl.getMsgId());
            msg.setToOpenId(openId);
            HttpResponse ret = sendMsg(appId,msg);
            if(response == null){
                response = ret;
            }
            if(!ret.isSuccess()){
                response = ret;
            }
        }
        return response;
    }
}
